<?php /* 
==================================================
TextCMS -- simple plain/text CMS with GPL licence
Admincenter content editor module
(c) 2008, 4X_Pro
Visit us online: http://textcms.ru
==================================================
TODO:
Подумать над тем, как сделать вывод с учетом сортировки, но при этом чтобы не исчезали из виду
"потерянные элементы"
*/

/** Выводит список страниц CMS **/
function admcont_list() {
  cms_module_load('cmsmain',true);
  cms_module_load('menu',true);
  $list_page=cms_output_load_template('list.htm','admcont');
  $item_template=cms_output_load_template('item.htm','admcont');
  $items=menu_pages_get('/');
  $list_data['ITEMS']='';
  
  $cur=array();
  $max=array();
  for ($i=0, $count=count($items); $i<$count; $i++) {
    $cur[$items[$i]['url']]=$items[$i]['sort'];
    $dirname=dirname($items[$i]['url']);
    if ($dirname=='\\') $dirname='/';
    $max[$dirname]=(isset($max[$dirname]) && $max[$dirname]>$items[$i]['sort']) ? $max[$dirname] : $items[$i]['sort'];
  }
    
  for ($i=0; $i<$count; $i++) {
    $items[$i]['floatsort']=_admcont_floatsort($items[$i]['url'],$max,$cur);
  }
  
  if (is_array($items)) {
		usort($items,create_function('$a,$b','return ($a["floatsort"]>$b["floatsort"]) ? -1 : ($a["floatsort"]==$b["floatsort"]) ? 0 : 1;'));
		
		for ($i=0, $count=count($items); $i<$count; $i++) {
			if ($items[$i]['state']!=1) {
				$items[$i]['state']=$items[$i]['state']==2 ? '<span class="warn">Черновик</span>' : '<span class="ok">Опубликован</span>';
				$items[$i]['lastmod_date']='Последнее редактирование: '.strftime('%d.%m.%Y %H:%M',$items[$i]['lastmod']);
				if (trim($items[$i]['title'])=='') $items[$i]['title']='<Без заголовка>';
				$items[$i]['title']=htmlspecialchars($items[$i]['title']);
        $tmpurl=$items[$i]['url'];
        if (substr($tmpurl,-1,1)=='/' && $tmpurl!='/') $tmpurl=substr($tmpurl,0,-1);
        $items[$i]['whitespace']=str_repeat('&raquo;&nbsp;', substr_count($tmpurl,'/')-1);
				$list_data['ITEMS'].=cmsmain_replace($item_template,$items[$i]);
			}
		}
	}
  if (!$list_data['ITEMS']) $list_data['ITEMS']='На сайте нет еще ни одной страницы!';
  $page = cmsmain_replace($list_page,$list_data);
  if (isset($_SESSION['admcont']['status'])) {
    $status=$_SESSION['admcont']['status'];
    unset($_SESSION['admcont']['status']);
  }
  else $status='';
 //
  $page=str_replace('#message#','<div id="message">'.$status.'</div>',$page);
  
  return $page;
}

function _admcont_floatsort($url,$max,$cur) {
  if ($url=='/' || $url=='' || $url=='\\') return 1;  // Исправление бага, о котором сообщил igor.trifonov
  $dirname=dirname($url);
  $result = _admcont_floatsort($dirname,$max,$cur);
  $curvalue = isset($cur[$url]) ? $cur[$url] : $cur[$url.'/'];
  $result = $result - $curvalue/_admcont_recurse_max($dirname,$max);
  return $result;
}

function _admcont_recurse_max($url,$max) {
  if ($url=='/' || $url=='' || $url=='\\') return $max['/']+1;
  $result=$max[$url]+1;
  if ($result==0) $result=1;
  $result=$result*_admcont_recurse_max(dirname($url),$max);
  return $result;
}

/** Редактирование страницы и ее сохранение **/
function admcont_edit() {
  if (isset($_POST['return'])) {
    $GLOBALS['status']=302;
    $GLOBALS['location']='admin.php?a=admcont_list';
    return;
  }
  cms_module_load('cmsmain',true);
  cms_module_load('menu',true);
	$message='';
  $id = isset($_REQUEST['id']) ? $_REQUEST['id'] : false;
  $result=false;
  if (isset($_POST['save']) || isset($_POST['save_continue'])) { // если сохраняем страницу
    if ($_POST['hurl']=='') { // попытка получить hurl из текста страницы
      if (!$_POST['title']) { // если заголовок страницы не задан, берем его из первого элемента h1
        preg_match('|<h1>(.*?)</h1>|is',$_POST['text'],$matches);
        if (isset($matches[1])) {
          $_POST['title']=$matches[1];
        }
      }
      if (!$_POST['hurl']) $_POST['hurl']=$_POST['title'];
      $_POST['hurl']=cmsmain_transliterate($_POST['hurl']);
      $_POST['hurl']=str_replace(' ','_',$_POST['hurl']);
      $_POST['hurl']=preg_replace('|[^\w\d\-._]|is','',$_POST['hurl']);      
    }

    $data=$_POST;
    if (!isset($data['state'])) $data['state']=0;
    $data['hurl']=trim($data['hurl']);
    if ($GLOBALS['config']['nohtmpages']==0 && strpos($data['hurl'],'/')===false && !preg_match('/\.(html|htm|php|shtml)$/is',$data['hurl'])) $data['hurl'].='/'; // добавляем косую черту в URL, если включена соответствующая опция    
    $data['url'] = preg_replace('|/+|','/',$data['parent'].'/'.$data['hurl']);
    if (!$data['hurl']) { // если удалось сформировать hurl
      $message='Не указан HURL страницы и не удается получить его из содержимого!';
    }
    elseif ($data['hurl']!='/' && !preg_match('|^[\w\d\-._]+/?$|i',$data['hurl'])) {
      $message='HURL страницы содержит недопустимые символы! (Допустимыми являются латинские буквы, цифры, точка, прочерк и дефис).';
    }
    elseif ($data['hurl']=='/' && $data['parent']!='/') {
      $message='HURL вида / можно использовать только для корневого элемента сайта! Он не может быть вложенным в какой-либо раздел!';
    }
    else {
			if (isset($_POST['typograf']) && cms_module_load('typograf')) {
				$data['title']=preg_replace('|<span style="white-space: nowrap">(.*?)</span>|','$1',typograf_main($data['title']));
				$_POST['text']=typograf_main($_POST['text']);
			}
      $tmp = cms_page_info($data['url'],false);
      if ($tmp['url']==$data['url'] && $tmp['id']!=$_REQUEST['id']) { // если оказалось, что есть страница с другим id, но тем же в точности url
        $message = 'Ошибка: страница с таким URL уже существует!';
      } // если нет, сохраняем
      else {
        $data['lastmod']=time();
        $data['id']=$id;
        $data['date']=strtotime($data['date']);
        if (!isset($data['state'])) $data['state']=0;
        $data['id']=cmsmain_pageinfo_save($data,(isset($_POST['old_url']) && $_POST['old_url'] ? $_POST['old_url'] : false)); // сохраняем информацию о странице
        if (!$data['id']) $message='Ошибка: не удалось сохранить данные о странице!';
        else { // сохраняем саму страницу
					$result=cmsmain_page_save($data['id'],$data['state'],$_POST['text']);
					if (!$result) $message='Ошибка при сохранении страницы сайта в файл!';
        }
      }
    }
  } // если страницу не сохраняем
  else {
    if ($id) { // если передан id страницы, грузим ее данные
      $hurl=cmsmain_get_hurl($id);
      if ($hurl===false) {
        $message='Страница с указанным URL не найдена!';
        $data=false;
      }
      else {
        $data=cms_page_info($hurl);
				if (isset($_REQUEST['nodraft'])) $data['state']=false; // если выбран режим редактирования старого чистовика
				elseif ($data['state']==2) { // если нет, проверяем старый 
					$nodraftname = cms_page_filename($id,false);
					if (file_exists($nodraftname)) $message='Вы редактируете черновик страницы, однако имеется более старая чистовая версия. <a href="'.$_SERVER['REQUEST_URI'].'&amp;nodraft=1">Переключиться!</a> ';
				}
        $data['text']=cms_page_load($id,$data['state']);
        $pos=strrpos($data['url'],'/');
        if ($pos==strlen($data['url'])-1 && $pos!=0) $pos=strrpos(substr($data['url'],0,$pos-1),'/');
        if ($pos==0) $data['parent']='/';
        else $data['parent']=substr($data['url'],0,$pos+1);
        $data['hurl']=substr($data['url'],$pos+1);
        if ($data['url']=='/') $data['hurl']='/';
        $data['old_url']=$data['url'];
      }
    } // иначе задаем значение по умолчанию -- дату и пустой id
    else {
      $data['date']=time();
      $data['id']='';
      $data['parent']='/';
      $data['template']='';
      $data['sort']='0';
    }
  }
  if (!$result) { // если не было произведено успешное сохранение, то выводим страницу для редактирования
    if (is_numeric($data['date'])) $data['date']=strftime('%d.%m.%Y %H:%M',$data['date']);    
    $page_edit = cms_output_load_template('edit.htm','admcont');
    $params['template']=cmsmain_get_templates();
    $pages = menu_pages_get();
    $params['parent']=array();
    for ($i=0, $count=count($pages); $i<$count; $i++) {
      if ($data['id']!=$pages[$i]['id'] && substr($pages[$i]['url'],-1,1)=='/' && $pages[$i]['url']!='/' && $pages[$i]['state']!=1) {
          $params['parent'][$pages[$i]['url']]='('.$pages[$i]['title'].') '.$pages[$i]['url'];
      }
    }
    if (isset($data['text'])) $data['text']=str_replace('##','\\##',$data['text']);
		$data['nohtml']=isset($_REQUEST['nohtml']) ? '&nohtml='.$_REQUEST['nohtml'] : '';
    $page_edit = cmsmain_html_set($page_edit,$data,$params);
    // установка глобальных параметров для WYSIWYG
    $GLOBALS['wysiwyg_options']['css']=($data['template']) ? 'template/'.$data['template'].'/style.css' : 'template/'.$GLOBALS['config']['template'].'/style.css';
    // вывод сообщения, если нужно
    if ($message && !isset($nodraftname)) $page_edit=str_replace('#message#','<div id="message" class="errmsg">'.$message.'</div>',$page_edit);
		elseif (isset($nodraftname)) $page_edit=str_replace('#message#','<div id="message" class="warnmsg">'.$message.'</div>',$page_edit);
    else $page_edit=str_replace('#message#','<div id="message"></div>',$page_edit);
    return $page_edit;
  }
  else { // если сохранили, переходим к списку страниц
    $GLOBALS['status']=302;
    if (isset($_POST['save_continue'])) $GLOBALS['location']='admin.php?a=admcont_edit&id='.$data['id'].(isset($_REQUEST['nohtml']) ? '&nohtml='.$_REQUEST['nohtml'] : '');
    else $GLOBALS['location']='admin.php?a=admcont_list';
    $_SESSION['admcont']['status']='<div class="okmsg">Изменения успешно сохранены!</div>';
  }
}

/** Удаление/восстановление страницы. Планировалось еще также переключение черновика,
но впоследствии решил отказаться из-за того, что нужно проверять, 
есть ли старая чистовая версия или нет и хочет ли пользователь сохранить ее 
или сделать чистовиком новый черновик **/
function admcont_change() {
  $result=false;
  if ((strpos($_SERVER['HTTP_REFERER'],'http://')!==false || strpos($_SERVER['HTTP_REFERER'],'https://')!==false) && 
    strpos($_SERVER['HTTP_REFERER'],'admin.php')===false) $message='Подозрительный REFERER страницы! Действие не выполнено из соображений безопасности!';
  elseif (!isset($_GET['id'])) $message='Не указан id страницы для удаления!';
  else {
    $id=$_GET['id'];
    $change=$_GET['ch'];
    if (cms_module_load('cmsmain',true)) {    
      $hurl=cmsmain_get_hurl($id);
      if (!$hurl) $message='Страница с таким id не найдена!';
      else {
        $data=cms_page_info($hurl);
        if ($change=='delete') $data['state']=1;
//        elseif ($change=='draft') $data['state']=($data['state']==2) ? $data['state']=0 : $data['state']=2;
        elseif ($change=='restore') {
          if (file_exists(cms_page_filename($data['id'],true))) $data['state']=2;
            else $data['state']=0;
        }
        $result=(cmsmain_pageinfo_save($data)==$data['id']);
      }
    }
  }
  if ($result) {
    $GLOBALS['status']=302;
    if ($change=='delete') {
      $GLOBALS['location']='admin.php?a=admcont_list&ok=2';
      $message='<div class="okmsg">Страница удалена!</div>';
    }
    #elseif ($change=='draft') $GLOBALS['location']='admin.php?a=admcont_list&ok=1';
    elseif ($change=='restore') {
      $GLOBALS['location']='admin.php?a=admcont_trash&ok=1';
      $message='<div class="okmsg">Страница восстановлена!</div>';
    }
  }
  else $message='<div class="errmsg">'.$message.'</div>';
  $_SESSION['admcont']['status']=$message;
  return $message;
}

/** Вывод списка удаленных страниц и выполнение окончательного удаления **/
function admcont_trash() {
  cms_module_load('cmsmain',true);
  cms_module_load('menu',true);
  $list_page=cms_output_load_template('trash.htm','admcont');
  $item_template=cms_output_load_template('delitem.htm','admcont');
  $items=menu_pages_get('/');
  $list_data['ITEMS']='';
  
  for ($i=0, $count=count($items); $i<$count; $i++) {
    if ($items[$i]['state']==1) {
      if (!isset($_POST['delete_all'])) {
        if (trim($items[$i]['title'])=='') $items[$i]['title']='<Без заголовка>';
        $items[$i]['title']=htmlspecialchars($items[$i]['title']);
        $list_data['ITEMS'].=cmsmain_replace($item_template,$items[$i]);
      }
      elseif (isset($_POST['delete_all'])) { // если сделан запрос delete_all
        $filename=cms_page_filename($items[$i]['id'],true);
        if (file_exists($filename)) unlink($filename);
        $filename=cms_page_filename($items[$i]['id'],false);
        if (file_exists($filename)) unlink($filename);
        unset($items[$i]);
      }
    }
  }
  if (isset($_POST['delete_all'])) { // если сделан запрос delete_all и он подтвержден
    cmsmain_save_pageinfo_saveall($items);
    $GLOBALS['status']=302;
    $GLOBALS['location']='admin.php?a=admcont_trash';
  }
  if (!$list_data['ITEMS']) $list_data['ITEMS']='Нет ни одной удаленной страницы!';
  $list_page = cmsmain_replace($list_page,$list_data);
  
  $status='';
  if (isset($_SESSION['admcont']['status'])) {
    $status=$_SESSION['admcont']['status'];
    unset($_SESSION['admcont']['status']);
  }
  $list_page=str_replace('#message#','<div id="message">'.$status.'</div>',$list_page);
  return $list_page;
}

function admcont_resort() {
  if (isset($_POST['sort']) && is_array($_POST['sort'])) {  
    cms_module_load('menu',true);
    cms_module_load('cmsmain',true);
    $items = menu_pages_get();
    for ($i=0, $count=count($items); $i<$count; $i++) {
      if (isset($_POST['sort'][$items[$i]['id']])) $items[$i]['sort']=$_POST['sort'][$items[$i]['id']];
    }
    cmsmain_save_pageinfo_saveall($items);
  }
  $_SESSION['admcont']['status']='<div class="okmsg">Изменения успешно сохранены!</div>';  
  if (cms_ajax()) return $_SESSION['admcont']['status'];
  else { 
    $GLOBALS['status']=302;
    $GLOBALS['location']='admin.php?a=admcont_list';
  }
}

/** Редактирование и сохранение параметров работы CMS.
Вызывается также через admcont_password с параметром $password_mode=true **/
function admcont_params($password_mode=false) {
  $gzip_test=false;
  $filename=cms_basedir().'config.php';
  $result=false;
  $message='';
  
  if ($password_mode) { // обработка смены пароля
    if (isset($_POST['save'])) {
      if ($_POST['password1']!=$_POST['password2']) $message='Заданные пароли не совпадают!';
      elseif (strlen($_POST['password1'])<7) $message='Минимальная длина пароля -- 7 символов!';
      elseif ($_POST['oldpassword']!=$GLOBALS['config']['password']) $message='Неправильно указан старый пароль!';
      elseif ($_POST['password1']=='TextCMS') $message='Использовать пароль по умолчанию запрещено по соображениям безопасности!';
      else {
        $_POST['password']=$_POST['password1'];
        unset($_POST['password1']);
        unset($_POST['password2']);
        unset($_POST['oldpassword']);
      }
      if ($message) $message='<div class="errmsg">'.$message.'</div>';
    }
  }
  
  if ((isset($_POST['save']) || isset($_POST['gzip_confirm'])) && $message=='') {
    $tmpname=str_replace('.php','.tmp.php.',$filename);
    $fh=fopen($tmpname,'w');
    if (!$fh) trigger_error('Не удалось открыть файл на запись!'.$tmpname,E_USER_ERROR);
    else {
      flock($fh,LOCK_EX);
      $buffer="<?php\n";
      unset($_POST['save']);
      $savedata=array_merge($GLOBALS['config'],$_POST);
      foreach ($savedata as $key=>$value) {
        $key=str_replace('\'','\\\'',$key);
        $value=str_replace('\'','\\\'',$value);
        if ($key=='gzip' && $value && (!isset($GLOBALS['config']['gzip']) || !$GLOBALS['config']['gzip']) && !isset($_POST['gzip_confirm'])) {
          $buffer.='$GLOBALS[\'config\'][\''.$key.'\']=\'0'."';\n";
          $GLOBALS['config']['gzip']=1;
          $gzip_test=true;
        }
        elseif ($key!='save' && $key!='gzip_confirm') {
          $buffer.='$GLOBALS[\'config\'][\''.$key.'\']=\''.$value."';\n";
          $GLOBALS['config'][$key]=$savedata[$key];
        }
      }
      $buffer.="?>";
      $result=fputs($fh,$buffer);
      $result=$result && fclose($fh);
      if ($buffer) { 
        $oldname = str_replace('.php','.old.php',$filename);
        if (file_exists($oldname)) unlink($oldname);
        if (file_exists($filename)) $result=$result && rename($filename,$oldname);
        $result=$result && rename($tmpname,$filename);
				if (file_exists($tmpname)) unlink($tmpname); 
      }
    }
    if ($result) $message='<div id="message" class="okmsg">Изменения успешно сохранены!</div>';
    elseif (!is_writable(dirname($filename))) $message='<div id="message" class="warnmsg">Каталог '.dirname($filename).' недоступен для записи!</div>';
    elseif ($GLOBALS['config']['password']=='textCMS') $message='<div id="message" class="errmsg">У вас используется пароль доступа по умолчанию! Необходимо его сменить!</div>';
    else $message='';
    
    if (!$gzip_test) {
      $_SESSION['admcont']['status']=$message;
      $GLOBALS['status']=302;
      if ($password_mode) $GLOBALS['location']='admin.php?a=admcont_password';
      else $GLOBALS['location']='admin.php?a=admcont_params';
      return '';
    }
  }
  if ($gzip_test) $page = cms_output_load_template('gzip.htm','admcont');
  elseif ($password_mode) $page = cms_output_load_template('password.htm','admcont');
  else $page = cms_output_load_template('params.htm','admcont');
  
  if (isset($_SESSION['admcont']['status'])) {
    $message=$_SESSION['admcont']['status'];
    unset($_SESSION['admcont']['status']);
  }
  $page=str_replace('#message#',$message,$page);  
  
  cms_module_load('cmsmain',true);
  if (!$password_mode) $params['template']=cmsmain_get_templates();
  else $params=array();
  if (cms_module_load('wysiwyg')) $params['wysiwyg']=wysiwyg_list();

  $page = cmsmain_html_set($page,$GLOBALS['config'],$params);
  return $page;
}

/** Функция смены пароля. 
На самом деле все действия выполняются в admcont_params, 
которая вызывается с $password_mode=true,
что позволяет избежать дублирования кода сохранения конфигурации в файл. **/
function admcont_password() {
  return admcont_params(true);
}
